package com.swinginwind.owf.leave;

import java.io.IOException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import org.apache.commons.lang.StringUtils;

import com.swinginwind.JdbcHelper;
import com.swinginwind.core.print.PrintTableItemConfig;
import com.swinginwind.core.print.PrintTableVO;
import com.swinginwind.owf.leave.vo.LeaveVO;

import oracle.apps.fnd.wf.WFContext;
import oracle.apps.fnd.wf.engine.WFEngineAPI;

public class Test {

	public static void main(String[] args) throws SQLException, ClassNotFoundException, IOException
	{

		//startProcess();
		//rejectProccess("83");
		println("正在启动..");
		try
		{
			init(args);
		}
		catch(ClassNotFoundException e)
		{
			println("error: 数据库驱动加载失败, 程序已退出");
			System.exit(0);
		}
		catch(SQLException e1)
		{
			println("error: 数据库无法连接, 程序已退出");
			System.exit(0);
		}
		println("系统启动成功 ^^\n");
		//print(getAllProcessList());
		login();
		try
		{
			cmdHandler();
		}
		catch(Exception e)
		{
			println("error: " + e.getMessage());
		}

	}

	/**
	 * 初始化程序, 测试数据库连接
	 * @param args
	 * @throws ClassNotFoundException
	 * @throws SQLException
	 */
	public static void init(String[] args) throws ClassNotFoundException, SQLException
	{
		Class.forName("oracle.jdbc.OracleDriver");
		if(args != null && args.length == 3)
		{
			dbUrl = args[0];
			dbUserName = args[1];
			dbPassword = args[2];
		}
		else
		{
			println("使用默认配置");
		}
		println("连接字符串: " + dbUrl);
		println("用户名: " + dbUserName);
		println("密码: " + dbPassword);
		println("正在测试连接..");
		java.sql.Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
		conn.close();
		println("连接成功");
	}


	public static String dbUrl = "jdbc:oracle:thin:@192.168.1.100:1521:orcl";
	public static String dbUserName = "OWF_MGR";
	public static String dbPassword = "OWF_MGR";

	public static Scanner scanner=new Scanner(System.in);

	/**
	 * 当前用户名
	 */
	public static String currentUser;

	/**
	 * 从控制台获取输入的工具方法
	 * @return
	 * @throws IOException
	 */
	public static String getConsoleInString() throws IOException
	{
		String temp = scanner.nextLine();
		return temp;
	}

	/**
	 * 换行打印
	 * @param ob
	 */
	public static void println(Object ob)
	{
		if(ob instanceof List)
		{
			for(Object ob1 : (List)ob)
			{
				println(ob1);
			}
		}
		else if(ob instanceof Map)
		{
			Map map = (Map)ob;
			for(Object key : map.keySet())
			{
				System.out.print(StringUtils.rightPad(map.get(key) == null ? "" : map.get(key).toString(), 15));
			}
			System.out.println();
		}
		else if(ob instanceof PrintTableVO)
		{
			PrintTableVO ptv = (PrintTableVO)ob;
			if(ptv.getConfigList() != null && ptv.getDataList() != null)
			{
				if("table".equals(ptv.getPrintWay()))
				{
					for(PrintTableItemConfig config : ptv.getConfigList())
					{
						String displayName = config.getDisplayName() == null ? "" : config.getDisplayName();
						int size = config.getWidth() - displayName.length();
						System.out.print(StringUtils.rightPad(displayName, size));
					}
					System.out.println();
					for(Map map : ptv.getDataList())
					{
						for(PrintTableItemConfig config : ptv.getConfigList())
						{
							System.out.print(StringUtils.rightPad(map.get(config.getField()) == null ? "" : map.get(config.getField()).toString(), config.getWidth()));
						}
						System.out.println();
					}
				}
				else if("detail".equals(ptv.getPrintWay()))
				{
					for(Map map : ptv.getDataList())
					{
						for(PrintTableItemConfig config : ptv.getConfigList())
						{
							System.out.println(config.getDisplayName() + ":" + (map.get(config.getField()) == null ? "" : map.get(config.getField()).toString()));
						}
						System.out.println();
					}
				}
			}
		}
		else
			System.out.println(ob);
	}

	/**
	 * 不换行打印
	 * @param ob
	 */
	public static void print(Object ob)
	{
		System.out.print(ob);
	}

	/**
	 * 帮助
	 */
	public static void help()
	{
		println("help: 获取帮助");
		println("login: 重新登录");
		println("list all: 获取所有请假申请");
		println("list mytodo: 获取当前用户需要审批的申请");
		println("list mydone: 获取当前用户审批过的申请");
		println("list myapproved: 获取当前用户申请的同意的申请");
		println("list myrejected: 获取当前用户申请的拒绝的申请");
		println("list myapproving: 获取当前用户申请的正在审批中的申请");
		println("list myrerequest: 获取当前用户申请的被拒绝后需要重新发送的申请");
		println("detail: 获取申请详情");
		println("request: 申请新的请假");
		println("approve: 审批");
		println("rerequest: 重新发送");
	}

	/**
	 * 登录
	 * @throws IOException
	 * @throws SQLException
	 */
	public static void login() throws IOException, SQLException
	{
		currentUser = null;
		println("清输入用户名");
		String userName = getConsoleInString();
		if("".equals(userName))
		{
			println("用户名不能为空");
			login();
			return;
		}
		currentUser = userName;
		println("正在登录..");
		int myToDoCount = getMyToDoProcessList().size();
		int myReRequestCount = getMyProcessList(Constants.LEAVE_STATUS_RE_REQUEST).size();

		println(userName + " 登录成功   " + new Date().toLocaleString());
		if(myToDoCount > 0)
			println("您有" + myToDoCount + "条待审批任务, 详情请用list mytodo命令查看");
		if(myReRequestCount > 0)
			println("您有" + myReRequestCount + "条被拒绝申请, 详情请用list myrerequest命令查看");

	}


	/**
	 * 接收输入命令的处理方法
	 * @throws IOException
	 * @throws SQLException
	 */
	public static void cmdHandler() throws IOException, SQLException
	{
		System.out.print("owf>");
		String cmd = getConsoleInString();
		try
		{
			if("help".equals(cmd))
			{
				help();
			}
			else if("login".equals(cmd))
			{
				login();
			}
			else if("detail".equals(cmd))
			{
				printProcessDetail();
			}
			else if("list all".equals(cmd))
			{
				printAllProcess();
			}
			else if("list mytodo".equals(cmd))
			{
				printMyToDoProcess();
			}
			else if("list mydone".equals(cmd))
			{
				printMyDoneProcess();
			}
			else if("list myrejected".equals(cmd))
			{
				printMyProcess(Constants.LEAVE_STATUS_REJECTED);
			}
			else if("list myapproved".equals(cmd))
			{
				printMyProcess(Constants.LEAVE_STATUS_APPROVED);
			}
			else if("list myapproving".equals(cmd))
			{
				printMyProcess(Constants.LEAVE_STATUS_APPROVING);
			}
			else if("list myrerequest".equals(cmd))
			{
				printMyProcess(Constants.LEAVE_STATUS_RE_REQUEST);
			}
			else if("request".equals(cmd))
			{
				startProcessInit();
			}
			else if("approve".equals(cmd))
			{
				approveProcessInit();
			}
			else if("rerequest".equals(cmd))
			{
				reRequestProcessInit();
			}
			else
				println("无效的指令");

		}
		catch(Exception e)
		{
			println("error: " + e.getMessage());
		}
		//执行完成后继续接收输入
		cmdHandler();
	}


	/**
	 * 打印所有的请假申请
	 * @throws SQLException
	 */
	public static void printAllProcess() throws SQLException
	{
		println("正在打印..");
		PrintTableVO ptv = getDefaultPTVO();
		ptv.setDataList(getAllProcessList());
		println(ptv);
		println("打印完成");
	}

	/**
	 * 获取所有的请假申请
	 * @return
	 * @throws SQLException
	 */
	public static List getAllProcessList() throws SQLException
	{
		return JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, SqlStatements.BASE_ITEM_QUERY_SQL);
	}

	/**
	 * 打印当前用户需要审批的申请
	 * @throws SQLException
	 */
	public static void printMyToDoProcess() throws SQLException
	{
		println("正在打印..");
		PrintTableVO ptv = getDefaultPTVO();
		ptv.setDataList(getMyToDoProcessList());
		println(ptv);
		println("打印完成");
	}

	/**
	 * 获取当前用户需要审批的申请
	 * @return
	 * @throws SQLException
	 */
	public static List getMyToDoProcessList() throws SQLException
	{
		StringBuilder sb = new StringBuilder();
		sb.append("select * from (").append(SqlStatements.BASE_ITEM_QUERY_SQL).
		append(") t10 where t10.manager='").append(currentUser).append("' and t10.status='").append(Constants.LEAVE_STATUS_APPROVING).append("'");
		return JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, sb.toString());
	}

	/**
	 * 打印当前用户审批过的申请
	 * @throws SQLException
	 */
	public static void printMyDoneProcess() throws SQLException
	{
		println("正在打印..");
		PrintTableVO ptv = getDefaultPTVO();
		ptv.setDataList(getMyDoneProcessList());
		println(ptv);
		println("打印完成");
	}

	/**
	 * 获取当前用户审批过的申请
	 * @return
	 * @throws SQLException
	 */
	public static List getMyDoneProcessList() throws SQLException
	{
		StringBuilder sb = new StringBuilder();
		sb.append("select * from (").append(SqlStatements.BASE_ITEM_QUERY_SQL).
		append(") t10 where t10.manager='").append(currentUser).append("' and t10.activity_name='").append("END").append("'");
		return JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, sb.toString());
	}

	/**
	 * 打印当前用户发出的申请
	 * @param status 申请当前的状态
	 * @throws SQLException
	 */
	public static void printMyProcess(String status) throws SQLException
	{
		println("正在打印..");
		PrintTableVO ptv = getDefaultPTVO();
		ptv.setDataList(getMyProcessList(status));
		println(ptv);
		println("打印完成");
	}

	/**
	 * 获取当前用户发出的申请
	 * @param status 申请当前的状态
	 * @throws SQLException
	 */
	public static List getMyProcessList(String status) throws SQLException
	{
		StringBuilder sb = new StringBuilder();
		sb.append("select * from (").append(SqlStatements.BASE_ITEM_QUERY_SQL).
		append(") t10 where t10.employee='").append(currentUser).append("' and t10.status='").append(status).append("'");
		return JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, sb.toString());
	}



	/**
	 * 打印申请详情
	 * @param itemKey
	 * @throws SQLException
	 * @throws IOException 
	 */
	public static void printProcessDetail() throws SQLException, IOException
	{
		print("请输入ITEM_KEY: ");
		String itemKey = getConsoleInString();

		List list = getProcessDetailList(itemKey);
		if(list.size() == 0)
		{
			println("数据不存在!");
		}
		else
		{
			println("正在打印..");
			PrintTableVO ptv = getDefaultPTVO();
			ptv.setDataList(list);
			ptv.setPrintWay("detail");
			println(ptv);
			println("打印完成");
		}
	}

	/**
	 * 获取申请详情
	 * @param itemKey
	 * @throws SQLException
	 */
	public static List getProcessDetailList(String itemKey) throws SQLException
	{
		StringBuilder sb = new StringBuilder();
		sb.append("select * from (").append(SqlStatements.BASE_ITEM_QUERY_SQL).
		append(") t10 where t10.item_key='").append(itemKey).append("'");
		return JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, sb.toString());
	}







	/**
	 * 启动流程初始化
	 * @throws IOException
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void startProcessInit() throws IOException, SQLException, ClassNotFoundException
	{
		LeaveVO leave = new LeaveVO();
		print("请输入请假开始时间:");
		leave.setStartDate(getConsoleInString());
		print("请输入请假结束时间:");
		leave.setEndDate(getConsoleInString());
		print("请输入请假原因:");
		leave.setDesc(getConsoleInString());

		print("是否确认提交(Y/N): ");
		if("Y".equals(getConsoleInString()))
		{
			leave.setEmployee(currentUser);
			leave.setAppDate(dateToString(new Date(), "yyyy-MM-dd"));
			leave.setManager(getManagerByEmployee(currentUser));
			leave.setOrderId(dateToString(new Date(), "yyyyMMddhhmmss"));
			println("正在提交..");
			String itemKey = startProcess(leave);
			println("请假申请提交成功, 摘要如下:");
			println(leave.getPrompString());
			println("ITEM_KEY: " + itemKey);
		}
		else
			println("已取消");


	}


	/**
	 * 启动一个新的请假流程
	 * @param leave
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static String startProcess(LeaveVO leave) throws SQLException, ClassNotFoundException
	{
		WFContext wCtx = getWfContext();

		String itemKey = getItemKey();

		WFEngineAPI.createProcess(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_PROCESS);

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
		String orderId = sdf.format(new Date());

		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_APP_DATE, leave.getAppDate());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_EMPLOYEE, leave.getEmployee());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_MANAGER, leave.getManager());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_ORDER_ID, leave.getOrderId());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_START_DATE, leave.getStartDate());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_END_DATE, leave.getEndDate());
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_STATUS, Constants.LEAVE_STATUS_APPROVING);
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_DESC, leave.getDesc());


		WFEngineAPI.startProcess(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey);

		wCtx.releaseJDBCConnection();

		return itemKey;

	}


	/**
	 * 审批请假流程初始化
	 * @throws IOException
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void approveProcessInit() throws IOException, SQLException, ClassNotFoundException
	{
		print("请输入ITEM_KEY: ");
		String itemKey = getConsoleInString();
		print("是否审批通过(Y/N): ");
		String result = getConsoleInString();

		if("Y".equals(result))
		{
			println("正在审批..");
			approveProcess(itemKey);
			println("审批" + itemKey + "成功, 结果: 已批准");

		}
		else if("N".equals(result))
		{
			println("正在审批..");
			rejectProcess(itemKey);
			println("审批" + itemKey + "成功, 结果: 已拒绝");
		}
		else
		{
			println("无效的指令");
		}
	}

	/**
	 * 拒绝
	 * @param itemKey
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void rejectProcess(String itemKey) throws SQLException, ClassNotFoundException
	{
		WFContext wCtx = getWfContext();
		WFEngineAPI.completeActivity(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, "APPROVAL", Constants.LEAVE_LOOKUP_REJECTED);
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_STATUS, Constants.LEAVE_STATUS_RE_REQUEST);

		wCtx.releaseJDBCConnection();
	}

	/**
	 * 同意
	 * @param itemKey
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void approveProcess(String itemKey) throws SQLException, ClassNotFoundException
	{
		WFContext wCtx = getWfContext();
		WFEngineAPI.completeActivity(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, "APPROVAL", Constants.LEAVE_LOOKUP_APPROVED);
		WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_STATUS, Constants.LEAVE_STATUS_APPROVED);

		wCtx.releaseJDBCConnection();
	}


	/**
	 * 重新发送初始化
	 * @throws IOException
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void reRequestProcessInit() throws IOException, SQLException, ClassNotFoundException
	{
		print("请输入ITEM_KEY: ");
		String itemKey = getConsoleInString();
		print("是否 重新发送(Y/N): ");
		String result = getConsoleInString();
		if("Y".equals(result))
		{
			println("正在发送..");
			reRequestProcess(itemKey, result);
			println("重新发送" + itemKey + "已成功");

		}
		else if("N".equals(result))
		{
			println("正在取消..");
			reRequestProcess(itemKey, result);
			println("重新发送" + itemKey + "已取消");
		}
		else
		{
			println("无效的指令");
		}
	}


	/**
	 * 重新发送申请
	 * @param itemKey
	 * @param result
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static void reRequestProcess(String itemKey, String result) throws SQLException, ClassNotFoundException
	{
		WFContext wCtx = getWfContext();
		if("Y".equals(result))
		{
			WFEngineAPI.completeActivity(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, "RE_REQUEST", Constants.LEAVE_LOOKUP_YES);
			WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_STATUS, Constants.LEAVE_STATUS_APPROVING);

		}
		else if("N".equals(result))
		{
			WFEngineAPI.completeActivity(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, "RE_REQUEST", Constants.LEAVE_LOOKUP_NO);
			WFEngineAPI.setItemAttrText(wCtx, Constants.LEAVE_ITEM_TYPE, itemKey, Constants.LEAVE_ATTR_STATUS, Constants.LEAVE_STATUS_REJECTED);
		}
		wCtx.releaseJDBCConnection();
	}

	/**
	 * 获取一个WFContext
	 * @return
	 * @throws SQLException
	 * @throws ClassNotFoundException
	 */
	public static WFContext getWfContext() throws SQLException, ClassNotFoundException
	{
		Class.forName("oracle.jdbc.OracleDriver");
		java.sql.Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
		WFContext wCtx = new WFContext("utf-8");
		wCtx.setJDBCConnection(conn);
		return wCtx;
	}

	/**
	 * 获取一个新的ITEM_KEY
	 * @return
	 * @throws SQLException
	 */
	public static String getItemKey() throws SQLException
	{
		String itemKey = ((Map)JdbcHelper.jdbcQuery(dbUrl, dbUserName, dbPassword, SqlStatements.BASE_ITEM_KEY_SQL).get(0)).get("SEQ").toString();
		return itemKey;
	}

	/**
	 * 根据Employee获取Manager的名字, 只是一个Demo方法
	 * @param employee
	 * @return
	 */
	public static String getManagerByEmployee(String employee)
	{
		return employee + "_manager";
	}

	/**
	 * 日期转换为字符串的方法
	 * @param date
	 * @param pattern 日期格式
	 * @return
	 */
	public static String dateToString(Date date, String pattern)
	{
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}




	public static PrintTableVO getDefaultPTVO()
	{
		PrintTableVO vo = new PrintTableVO();
		vo.setConfigList(getDefaultPTConfigList());
		return vo;
	}


	public static List<PrintTableItemConfig> defaultPTConfigList;

	public static List<PrintTableItemConfig> getDefaultPTConfigList()
	{
		if(defaultPTConfigList == null)
		{
			List<PrintTableItemConfig> configList = new ArrayList<PrintTableItemConfig>();
			PrintTableItemConfig config = new PrintTableItemConfig("项类型", "ITEM_TYPE", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("项编号", "ITEM_KEY", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("申请时间", "APP_DATE", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("申请人", "EMPLOYEE", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("领导", "MANAGER", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("请假开始时间", "APP_START_DATE", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("请假结束时间", "APP_END_DATE", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("当前状态", "STATUS", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("当前任务人", "ASSIGNED_USER", 15, "left");
			configList.add(config);
			config = new PrintTableItemConfig("当前阶段", "ACTIVITY_NAME", 15, "left");
			configList.add(config);
			defaultPTConfigList = configList;
		}
		return defaultPTConfigList;
	}











}










